Générateur de faux français
Nous allons créer un générateur de faux français capable de s'entraîner en lisant des livres. En partant d'un long texte il est possible d'étudier statistiquement la répartition des lettres pour écrire automatiquement une oeuvre... qui n'aura certainement pas beaucoup de sens.
Nous allons suivre plusieurs étapes pour réaliser ce programme :
- Ouverture et lecture d'un fichier texte par python : représentation par une chaîne de caractère.
- Parcour de chaque caractère du texte et comptage des lettres et de leurs successeurs : représentation dans un dictionnaire dont les clés sont les lettres
- Tirer une lettre au hasard en respectant la pondération
- Ecriture d'un nouveau texte en respectant les
ILecture d'un long texte
Créer un nouveau fichier
faux_français.py
.
Pour lire un fichier, il faut d'abord l'ouvrir et retenir sa référence dans la variable
f
en tapant :
f=open ("dossiers/nom_du_fichier.txt",'r')
Une fois ouvert, pour lire son contenu entièrement et l'affecter à une variable :
contenu=f.read ()
Ne pas oublier de fermer le fichier pour éviter les mauvaises surprises :
f.close ()
Le 'r' dans
open
signifie "read", c'est à dire que le fichier ne sera ouvert qu'en écriture. Pour modifier le fichier, il faut mettre 'w' (write).
- Télécharger un des textes suivant et l'enregistrer dans le même dossier que votre programme : Le seigneur des anneaux - tome 1 , Une vie
- Lire le fichier entier et le stocker dans une variable txt
- Créer un dictionnaire appelé (lettres) dont les clés sont les lettres du texte et dont les valeurs sont le nombre d'occurence de la lettre dans le texte.
- Utiliser os.open () et os.read () pour lire le fichier.
- Créer un dictionnaire vide lettres={}
-
Ecrire une boucle sur les caractères de
txt
de la manière suivante : for c in txt:c sera le caractère visité.
... - Pour vérifier si c est déjà dans le dictionnaire lettres , utiliser in . Si il y est, on peut incrémenter la valeur de lettres[c]
La variable
lettres
devrait ressembler à
{'j':4670, 'r':61280, ...}
IITable des transitions
Nous souhaitons créer la table des transitions, c'est à dire le tableau comptant, pour chaque lettre, le nombre de ses successeurs possibles :
a | b | ... | z | |
a | \(N_{a\rightarrow a}\) | \(N_{a\rightarrow b}\) | ... | \(N_{a\rightarrow z}\) |
b | \(N_{b\rightarrow a}\) | \(N_{b\rightarrow b}\) | ... | \(N_{b\rightarrow z}\) |
... | ... | ... | ... | ... |
z | \(N_{z\rightarrow a}\) | \(N_{z\rightarrow b}\) | ... | \(N_{z\rightarrow z}\) |
Dans notre cas, il y aura plus de 26 entrées à ce tableau car le texte contient majuscules, espaces, ponctuations et sauts de lignes (représentés par '\n')
Nous représenterons cette table par un dictionnaire table dont les clés sont les lettres du texte et les valeurs un autre dictionnaire dont les clés sont les succésseurs et les valeurs sont leur nombre.
La table de transition ressemblera à :
table = {
'J':{"'": 254, '.': 1, 'a': 15, 'e': 790, 'o': 23, 'u': 25, '’': 1},
...
'a': {' ': 7, ' ': 206, ',': 1, 'C': 2, 'D': 6, ... },
}
'J':{"'": 254, '.': 1, 'a': 15, 'e': 790, 'o': 23, 'u': 25, '’': 1},
...
'a': {' ': 7, ' ': 206, ',': 1, 'C': 2, 'D': 6, ... },
}
Cela signifie que la lettre 'J' est suivie 254 fois d'une apostrophe, une fois d'un point, 15 fois de la lettre 'a', etc.
La lettre 'a' est suivie 7 fois d'un saut de ligne, 206 fois d'un espace, etc.
Créer un dictionnaire appelé (table) qui donne la table des transitions
- Créer un dictionnaire vide table={}
-
Ecrire une boucle sur
i
allant de
0
à
len (txt)-1
la longueur (moins un) du texte de la manière suivante : for i in range (0,len (txt)):i sera la position du caractère visité et i+1 la position du suivant.
... - Si on appelle c1 le caractère visité et c2 le caractère suivant, la valeur de table[c1][c2] contient le nombre de fois que le caractère c2 suit le caractère c1 .
- Comme pour lettres , faire attention à initialiser table[c1]={} au bon moment.
- Comme pour lettres , vérifier si c2 est dans table[c1] avant d'incrémenter table[c1][c2] .
IIITirer une lettre au hasard
Afin de simuler le hasard, nous allons utiliser la bibliothèque
random
. Pour cela, il faut ajouter
import random
au début du programme
Importer la bibliothèque
import random
dans votre fichier.
Le module random permet notamment de :
- Tirer un flottant au hasard entre 0 et 1 : random.random ()
- Tirer un nombre entier au hasard entre deux valeurs \(n\) et \(m\) : random.randint (n,m)
- Choisir un élément au hasard dans une liste L donnée : random.choice (L)
- Choisir un élément au hasard dans une liste L donnée : random.choice (L)
Dans la console, importer
import random
puis :
- Ecrire une commande qui permet de tirer à 'pile' ou 'face'
- Ecrire une commande qui permet de tirer une lettre de l'alphabet au hasard
Les commandes précédents font des tirages uniformes. Il faudra programmer un peu pour tenir compte des pondérations de notre table.
Créer une fonction
choix (T,n)
qui prend comme arguments
T
la table des transitions d'une lettre et
n
le nombre total de transitions et qui renvoie une lettre tirée au hasard en respectant les pondérations.
Pour
T={'a':2, 'b':1, 'c':'3'}
et
n=5
, la fonction renverra 'a', 'b' ou 'c' avec les probabilités de \(\frac{2}{5}\), \(\frac{1}{5}\) et \(\frac{3}{5}\).
Le total
n
pourrait se calculer à partir de
T
, mais comme il est donné dans notre cas par les valeurs de
lettres
, le mettre en argument évitera de le recalculer inutilement plusieurs fois.
L'idée est de tirer un nombre entier
i
au hasard entre
0
et
n
et de balayer la table de transition pour voir au niveau de quelle lettre on tombe.
En reprenant l'exemple précédent, on va tirer un nombre au hasard entre 0 et 5. Par exemple 4. On parcourt alors la table :
a | b | c |
2 | 1 | 3 |
- Pour 'a' : 2 <4 donc on continue.
- Pour 'b' : 2+1=3<4 donc on continue.
- Pour 'c' : 3 + 3 ≥ 6 donc on renvoie 'c'
def choix (T,n):
r=random.randint (0,n)
k=0
for c in T:
k=k+T[c]
if k>=n:
return c
return c
r=random.randint (0,n)
k=0
for c in T:
k=k+T[c]
if k>=n:
return c
return c
IVGénérer un texte
Il ne reste qu'à exploiter la table de transitions table et la fonction choix :
Créer une fonction
generateur (lettres,table,N)
qui prend comme arguments
lettres
le dictionnaire comptant les lettres,
table
la table des transitions des lettres,
N
un entier et qui renvoie un texte aléatoire de
N
caractères.
- On commence par une lettre c tirée au hasard
- Il va falloir faire une boucle de N itération
- A chaque étape, on tire au hasard la nouvelle lettre à l\'aide de choix table[c] et lettres[c] (le nombre de transitions).
- A l'étape suivante, on prend la lettre précédemment tirée comme point de départ.
VAller plus loin
On peut imaginer des moyens simples d'améliorer la qualité du texte généré aléatoirement en modifiant quelques éléments :
- On peut essayer d'entraîner le générateur sur des textes différents ou plus longs.
-
On peut calculer une table des transitions entre une lettre et plusieurs successeurs \(N_{x\rightarrow yz}\) :
aa ab ... zz a \(N_{a\rightarrow aa}\) \(N_{a\rightarrow ab}\) ... \(N_{a\rightarrow zz}\) b \(N_{b\rightarrow aa}\) \(N_{b\rightarrow ab}\) ... \(N_{b\rightarrow zz}\) ... ... ... ... ... zz \(N_{z\rightarrow aa}\) \(N_{z\rightarrow ab}\) ... \(N_{z\rightarrow zz}\) - On peut également choisir une approche basée non pas sur les caractères, mais sur les mots.